#pragma once
#include <string>
#include <iostream>

#include <memory>
#include <functional>
#include <mutex>
#include <unordered_map>
#include "channel.hpp"

namespace ns_rabbitmq
{
    class Connection
    {
        public:
        Connection(const muduo::net::TcpConnectionPtr &conn,
                   const ProtobufCodecPtr &codec, const ConsumerManangerPtr &cmp, const HostPtr &hostptr, const ThreadPoolPtr &poolptr)
            : _conn(conn), _codec(codec), _cmp(cmp),
              _hostptr(hostptr), _poolptr(poolptr), _channels(std::make_shared<ChannelManager>()) {}
        void OpenChannel(const OpenChannelRequestptr &req)
        {
            bool ret = _channels->OpenChannel(req->cid(), _conn, _codec, _cmp, _hostptr, _poolptr);
            if (!ret)
            {
                DLOG( "已经存在信道%s,不能再次创建", req->cid().c_str());
                return BasicResponse(false, req->rid(), req->cid());
            }
            return BasicResponse(true, req->rid(), req->cid());
        }

        void CloseChannel(const CloseChannelRequestptr &req)
        {
            _channels->CloseChannel(req->cid());
            return BasicResponse(true, req->rid(), req->cid());
        }

        ChannelPtr GetChannel(const std::string &cid)
        {
            return _channels->GetChannel(cid);
        }

    private:
        void BasicResponse(bool ok, const std::string &rid, const std ::string &cid)
        {
            BasicCommResponseptr resp=std::make_shared<BasicCommResponse>();
            resp->set_rid(rid);
            resp->set_cid(cid);
            resp->set_ok(ok);
            _codec->send(_conn, *resp);
        }

    private:
        muduo::net::TcpConnectionPtr _conn;
        ProtobufCodecPtr _codec;
        ConsumerManangerPtr _cmp; // 消费者队列管理句柄
        HostPtr _hostptr;
        ThreadPoolPtr _poolptr;
        ChannelManagerPtr _channels;
    };

    using ConnectionPtr = std::shared_ptr<Connection>;
    class ConnectionManager
    {
    public:
        ConnectionManager() {}

        void NewConnection(const muduo::net::TcpConnectionPtr &conn,
                           const ProtobufCodecPtr &codec, const ConsumerManangerPtr &cmp, const HostPtr &hostptr, const ThreadPoolPtr &poolptr)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _connections.find(conn);
            if (it != _connections.end())
            {
               DLOG( "已经存在连接,不能再次创建");
                return;
            }
            ConnectionPtr connect = std::make_shared<Connection>(conn, codec, cmp, hostptr, poolptr);
            _connections.insert(std::make_pair(conn, connect));
        }

        void DeleteConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _connections.erase(conn);
        }
        ConnectionPtr GetConnPtr(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _connections.find(conn);
            if (it == _connections.end())
            {
                DLOG("不存在连接!");
                return ConnectionPtr();
            }
            return it->second;
        }

    private:
        std::mutex _mutex;
        std::unordered_map<muduo::net::TcpConnectionPtr, ConnectionPtr> _connections;
    };

    using ConnectionManagerPtr=std::shared_ptr<ConnectionManager>;
}